package com.xxx.car.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xxx.car.constants.CarStatus;
import com.xxx.car.constants.CouponStatus;
import com.xxx.car.entity.*;
import com.xxx.car.entity.vo.request.*;
import com.xxx.car.entity.vo.response.*;
import com.xxx.car.mapper.*;
import com.xxx.car.service.*;
import com.xxx.car.utils.GsonUtils;
import com.xxx.common.base.exception.BizException;
import com.xxx.common.base.vo.APIResponse;
import com.xxx.common.util.IdWorker;
import jdk.nashorn.internal.runtime.options.Option;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by youxiaojia on 2017/6/20.
 */
@Service
public class TravelAppealServiceImpl implements TravelAppealService {
    @Autowired
    TbTravelOrderMapper tbTravelOrderMapper;
    @Autowired
    ITbMapper iTbMapper;
    @Autowired
    TbAppealMapper tbAppealMapper;
    @Autowired
    UserCarService userCarService;
    @Autowired
    IdWorker idWorker;
    @Autowired
    UserWalletService userWalletService;
    @Autowired
    CouponService couponService;
    @Autowired
    InvoiceService invoiceService;
    @Autowired
    TbUserMapper tbUserMapper;
    @Autowired
    TbRefundMapper tbRefundMapper;

    @Override
    public RespUserTravelOrder queryUserTravelOrderList(ReqUserTravelOrderQuery reqUserTravelOrderQuery) {
        PageHelper.startPage(reqUserTravelOrderQuery.getPageNum(), reqUserTravelOrderQuery.getPageSize());
        List<Integer> travelIds = new ArrayList<>();
        if (reqUserTravelOrderQuery.getIsInvoice().equals("true")){
            List<TbInvoice> invoiceList = invoiceService.queryInvoiceList(reqUserTravelOrderQuery.getUserId());
            if (!CollectionUtils.isEmpty(invoiceList)){
                for (TbInvoice tbInvoice : invoiceList){
                    if (tbInvoice.getTravelIds() != null){
                        String[] travelIdArray = org.apache.commons.lang3.StringUtils.split(tbInvoice.getTravelIds(), ",");
                        for (String str : travelIdArray){
                            travelIds.add(Integer.parseInt(str));
                        }
                    }
                }
            }
        }
        if (reqUserTravelOrderQuery.getIsRefund().equals("true")){
            TbRefundExample refundExample = new TbRefundExample();
            TbRefundExample.Criteria criteria = refundExample.createCriteria();
            criteria.andUserIdEqualTo(reqUserTravelOrderQuery.getUserId());
            List<TbRefund> refundList = tbRefundMapper.selectByExample(refundExample);
            if (!CollectionUtils.isEmpty(refundList)){
                for (TbRefund tbRefund : refundList){
                    if (tbRefund.getTravelOrderId() != null){
                        travelIds.add(tbRefund.getTravelOrderId());
                    }
                }
            }
        }
        TbTravelOrderExample tbTravelOrderExample = new TbTravelOrderExample();
        TbTravelOrderExample.Criteria criteria = tbTravelOrderExample.createCriteria();
        criteria.andUserIdEqualTo(reqUserTravelOrderQuery.getUserId());
        criteria.andStatusGreaterThan((byte)0);
        if (reqUserTravelOrderQuery.getIsInvoice().equals("true") && !CollectionUtils.isEmpty(travelIds)) {
            criteria.andIdNotIn(travelIds);
        }
        if (reqUserTravelOrderQuery.getIsRefund().equals("true") && !CollectionUtils.isEmpty(travelIds)) {
            criteria.andIdIn(travelIds);
        }
        if (reqUserTravelOrderQuery.getIsRefund().equals("true") && CollectionUtils.isEmpty(travelIds)){
            return null;
        }
        tbTravelOrderExample.setOrderByClause(" create_time desc ");
        List<TbTravelOrder> tbTravelOrderList = tbTravelOrderMapper.selectByExample(tbTravelOrderExample);

        HashMap map = (HashMap) iTbMapper.queryUserTravelOrderDistanceAndAmount(reqUserTravelOrderQuery.getUserId());

        RespUserTravelOrder respUserTravelOrder = new RespUserTravelOrder();
        respUserTravelOrder.setTotalAmount((BigDecimal) MapUtils.getObject(map,"totalAmount"));
        respUserTravelOrder.setTotalDistance((Double) MapUtils.getObject(map,"totalDistance"));
        respUserTravelOrder.setTravelOrderList(tbTravelOrderList);
        return respUserTravelOrder;
    }

    @Override
    public TbTravelOrder queryUserTravelOrderDetail(ReqUserTravelOrderQuery reqUserTravelOrderQuery) {
        if (reqUserTravelOrderQuery.getId() == null){
            return null;
        }
        TbTravelOrder tbTravelOrder = tbTravelOrderMapper.selectByPrimaryKey(reqUserTravelOrderQuery.getId());
        return tbTravelOrder;
    }

    @Override
    public List<TbAppeal> queryUserAppealList(ReqUserAppealQuery reqUserAppealQuery) {
        PageHelper.startPage(reqUserAppealQuery.getPageNum(), reqUserAppealQuery.getPageSize());
        TbAppealExample tbAppealExample = new TbAppealExample();
        TbAppealExample.Criteria criteria = tbAppealExample.createCriteria();
        criteria.andUserIdEqualTo(reqUserAppealQuery.getUserId());
        tbAppealExample.setOrderByClause(" create_time desc ");
        List<TbAppeal> tbAppealList = tbAppealMapper.selectByExample(tbAppealExample);
        return tbAppealList;
    }

    @Override
    public APIResponse submitUserAppeal(ReqAppeal reqAppeal) {
        TbAppeal tbAppeal = new TbAppeal();
        BeanUtils.copyProperties(reqAppeal,tbAppeal);
        tbAppeal.setStatus((byte)0);
        try {
            int result = tbAppealMapper.insertSelective(tbAppeal);
            if (result == 1){
                return APIResponse.returnSuccess("提交申诉成功");
            }
        } catch (Exception e) {
            return APIResponse.returnFail("申诉不可重复提交");
        }

        return APIResponse.returnFail("提交申诉失败");
    }

    @Override
    public TbAppeal queryUserAppealDetail(ReqUserAppealQuery reqUserAppealQuery) {
        if (reqUserAppealQuery.getId() == null){
            return null;
        }
        TbAppeal tbAppeal = tbAppealMapper.selectByPrimaryKey(reqUserAppealQuery.getId());
        return tbAppeal;
    }

    @Override
    public TbAppeal queryUserAppealDetailByTravelOrderId(Integer travelOrderId) {
        TbAppealExample tbAppealExample = new TbAppealExample();
        TbAppealExample.Criteria criteria = tbAppealExample.createCriteria();
        criteria.andTravelOrderIdEqualTo(travelOrderId);
        List<TbAppeal> tbAppealList = tbAppealMapper.selectByExample(tbAppealExample);
        if (!CollectionUtils.isEmpty(tbAppealList)){
            return tbAppealList.get(0);
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
    public void updateUserAppealDetail(ReqAppeal reqAppeal) throws Exception{
        TbAppealExample tbAppealExample = new TbAppealExample();
        TbAppealExample.Criteria criteria = tbAppealExample.createCriteria();
        criteria.andUserIdEqualTo(reqAppeal.getUserId());
        criteria.andTravelOrderIdEqualTo(reqAppeal.getTravelOrderId());
        criteria.andStatusEqualTo((byte)0);

        TbAppeal tbAppeal = new TbAppeal();
        BeanUtils.copyProperties(reqAppeal,tbAppeal);
        int result = tbAppealMapper.updateByExampleSelective(tbAppeal,tbAppealExample);
        if (result != 1){
            throw new BizException("正在审核中..");
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
    public String createStartTravel(String carNo, String gaosuName, String roadName, String stateName) throws Exception {
        TbTravelOrder tbTravelOrder = new TbTravelOrder();
        TbUserCar tbUserCar = userCarService.getCarByCarNo(carNo);
        if (tbUserCar==null){
            throw new BizException("用户车辆未录入系统");
        }
        //查询行驶中的车辆行程
        TbTravelOrder drivingTravelOrder = queryDrivingTravelOrder(tbUserCar.getCarId());
        if (drivingTravelOrder != null){
            //throw new BizException("已存在相同车辆进站行驶中");
            return finishTravel(carNo,gaosuName,roadName,stateName,new BigDecimal(50),new BigDecimal(3));
        }
        if (tbUserCar.getCarStatus() != null && tbUserCar.getCarStatus() != CarStatus.AUDIT_SUCCESS){
            throw  new BizException("该车辆未通过审核");
        }
        tbTravelOrder.setUserId(tbUserCar.getUserId());
        tbTravelOrder.setCarId(tbUserCar.getCarId());
        tbTravelOrder.setCarNo(tbUserCar.getCarPlateNumber());
        tbTravelOrder.setOrderNo(String.valueOf(idWorker.nextId()));
        tbTravelOrder.setStatus((byte)0);
        tbTravelOrder.setStart(gaosuName+"|"+roadName+"-"+stateName);
        tbTravelOrder.setStartTime(new Date());

        int result = tbTravelOrderMapper.insertSelective(tbTravelOrder);
        if (result > 0){
            RespCallback respCallback = new RespCallback();
            RespAlarm respAlarm = new RespAlarm();
            respAlarm.setInfo("ok");
            respAlarm.setContent(carNo);
            respCallback.setResponse_AlarmInfoPlate(respAlarm);
            return GsonUtils.toJson(respCallback);
        }
        RespCallback respCallback = new RespCallback();
        RespAlarm respAlarm = new RespAlarm();
        respAlarm.setInfo("err");
        respAlarm.setContent("创建行程单失败");
        respCallback.setResponse_AlarmInfoPlate(respAlarm);
        return GsonUtils.toJson(respCallback);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
    public String finishTravel(String carNo, String gaosuName, String roadName, String stateName, BigDecimal distance,BigDecimal price) throws Exception {
        TbUserCar tbUserCar = userCarService.getCarByCarNo(carNo);
        if (tbUserCar==null){
            throw new BizException("用户车辆未录入系统");
        }
        //查询行驶中的车辆行程
        TbTravelOrder tbTravelOrder = queryDrivingTravelOrder(tbUserCar.getCarId());
        if (tbTravelOrder == null){
            //throw new BizException("该车辆未进站行驶");
            return createStartTravel(carNo, gaosuName, roadName, stateName);
        }
        if (tbUserCar.getCarStatus() != null && tbUserCar.getCarStatus() != CarStatus.AUDIT_SUCCESS){
            throw  new BizException("该车辆未通过审核");
        }
        tbTravelOrder.setStatus((byte)1);
        tbTravelOrder.setEnd(gaosuName+"|"+roadName+"-"+stateName);
        tbTravelOrder.setEndTime(new Date());
        tbTravelOrder.setDistance(distance.doubleValue());
        BigDecimal travelOrderPrice = distance.multiply(price).setScale(2);
        tbTravelOrder.setAmount(travelOrderPrice);
        tbTravelOrder.setTime((int)getTravelOrderTime(tbTravelOrder.getStartTime(),tbTravelOrder.getEndTime()));

        TbTravelOrderExample tbTravelOrderExample = new TbTravelOrderExample();
        TbTravelOrderExample.Criteria criteria = tbTravelOrderExample.createCriteria();
        criteria.andCarIdEqualTo(tbUserCar.getCarId());
        criteria.andStatusEqualTo((byte)0);
        int result = tbTravelOrderMapper.updateByExampleSelective(tbTravelOrder,tbTravelOrderExample);
        if (result != 1){
            throw new BizException("出站记录失败");
        }

        //行程结算
        this.travelOrderPay(tbTravelOrder);

        RespCallback respCallback = new RespCallback();
        RespAlarm respAlarm = new RespAlarm();
        respAlarm.setInfo("ok");
        respAlarm.setContent(carNo);
        respCallback.setResponse_AlarmInfoPlate(respAlarm);
        return GsonUtils.toJson(respCallback);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
    public APIResponse travelRefund(Integer travelOrderId, String operater) {
        TbTravelOrder tbTravelOrder = tbTravelOrderMapper.selectByPrimaryKey(travelOrderId);
        if (tbTravelOrder == null){
            return APIResponse.returnFail("查无此行程");
        }
        TbRefund tbRefund = new TbRefund();
        tbRefund.setUserId(tbTravelOrder.getUserId());
        TbUser tbUser = tbUserMapper.selectByPrimaryKey(tbTravelOrder.getUserId());
        if (tbUser == null){
            return APIResponse.returnFail("查无此用户");
        }
        if (tbUser.getMobile() == null){
            return APIResponse.returnFail("用户账户异常");
        }
        tbRefund.setMobile(tbUser.getMobile());
        tbRefund.setTravelOrderId(travelOrderId);
        tbRefund.setAmount(tbTravelOrder.getAmount());
        tbRefund.setOperater(operater);
        tbRefundMapper.insertSelective(tbRefund);

        //结算
        try{
            userWalletService.changeAmt(tbTravelOrder.getUserId(),tbTravelOrder.getAmount().longValue()*100,BigDecimal.ZERO,0,0);
        }catch (Exception e){
            throw new BizException("行程退款失败:"+e.getMessage());
        }
        return APIResponse.returnSuccess();
    }

    @Override
    public PageInfo queryAppealAdminList(ReqAppealAdminQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<RespAppeal> respAppealList = iTbMapper.queryAppealAdminList(query);
        return new PageInfo<>(respAppealList);
    }

    @Override
    public int countCompleteAppeal() {
        TbAppealExample tbAppealExample = new TbAppealExample();
        TbAppealExample.Criteria criteria = tbAppealExample.createCriteria();
        criteria.andStatusEqualTo((byte)1);
        int result = tbAppealMapper.countByExample(tbAppealExample);
        return result;
    }

    @Override
    public APIResponse updateAppealReply(ReqAppealUpdate update) {
        TbAppeal tbAppeal = new TbAppeal();
        BeanUtils.copyProperties(update,tbAppeal);
        if (update.getIsAgree()==0){
            tbAppeal.setStatus((byte)2);
        }
        if (update.getIsAgree()==1){
            tbAppeal.setStatus((byte)1);
        }

        TbAppealExample tbAppealExample = new TbAppealExample();
        TbAppealExample.Criteria criteria = tbAppealExample.createCriteria();
        criteria.andStatusEqualTo((byte)0);
        criteria.andIdEqualTo(update.getAppealId());
        int result = tbAppealMapper.updateByExampleSelective(tbAppeal,tbAppealExample);
        if (result != 1) {
            return APIResponse.returnFail("申诉已被处理,不能修改");
        }
        if (update.getIsAgree()==1){
            travelRefund(update.getTravelOrderId(), "管理员");
        }
        return APIResponse.returnSuccess();
    }

    @Override
    public PageInfo queryRefundAdminList(ReqRefundAdminQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<TbRefund> tbRefundList = iTbMapper.queryRefundAdminList(query);
        return new PageInfo<>(tbRefundList);
    }

    @Override
    public Map totalRefundAmountAndRefundCount() {
        return iTbMapper.totalRefundAmountAndRefundCount();
    }

    @Override
    public List<RespRefundDetail> selectRefundDetail(ReqRefundAdminQuery query) {
        return iTbMapper.selectRefundDetail(query);
    }

    @Override
    public PageInfo queryFeedAdminList(ReqFeedAdminQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<RespFeedBack> tbFeedList = iTbMapper.queryFeedAdminList(query);
        return new PageInfo<>(tbFeedList);
    }

    @Override
    public Map totalCompeleteAndUncompelete() {
        return iTbMapper.totalCompeleteAndUncompelete();
    }

    @Override
    public APIResponse updateFeedReply(ReqFeedUpdate update) {
        iTbMapper.updateFeedReply(update);
        return APIResponse.returnSuccess();
    }

    @Override
    public RespTotalConsume queryConsumerTotal(ReqConsumeQuery reqConsumeQuery) {
        if (StringUtils.isNoneBlank(reqConsumeQuery.getMobile())) {
            List<TbUser> tbUsers = iTbMapper.getAppUserByMobile(reqConsumeQuery.getMobile());
            if (tbUsers != null && !tbUsers.isEmpty()) {
                reqConsumeQuery.setUserId(tbUsers.get(0).getId());
            }
        }
        return iTbMapper.queryConsumeTotal(reqConsumeQuery);
    }

    @Override
    public Page<RespUserConsume> queryConsumeList(ReqConsumeQuery reqConsumeQuery) {
        if (StringUtils.isNoneBlank(reqConsumeQuery.getMobile())) {
            List<TbUser> tbUsers = iTbMapper.getAppUserByMobile(reqConsumeQuery.getMobile());
            if (tbUsers != null && !tbUsers.isEmpty()) {
                reqConsumeQuery.setUserId(tbUsers.get(0).getId());
            }
        }
        PageHelper.startPage(reqConsumeQuery.getPageNum(), reqConsumeQuery.getPageSize());
        Page<TbUserConsume> page = (Page<TbUserConsume>) iTbMapper.queryConsumeList(reqConsumeQuery);

        Page<RespUserConsume> res = new Page<>(page.getPageNum(), page.getPageSize());
        res.setTotal(page.getTotal());

        if (page.size() > 0) {
            List<Integer> userIds = page.stream().map(e -> e.getUserId()).collect(Collectors.toList());
            List<TbUser> users = iTbMapper.findUserByIds(userIds);
            List<RespUserConsume> r = page.stream().map(e -> {
                RespUserConsume consume = new RespUserConsume();
                BeanUtils.copyProperties(e, consume);

                users.stream().filter(u -> u.getId() ==  consume.getUserId()).findFirst().ifPresent(k -> {
                    consume.setMobile(k.getMobile());
                });

                return consume;
            }).collect(Collectors.toList());

            res.addAll(r);
        }

        return res;
    }

    @Override
    public RespCarStatisticsTotal queryCarTotal(ReqCarStatistics reqCarStatistics) {
        return iTbMapper.queryCarTotal(reqCarStatistics);
    }

    @Override
    public Page<TbTravelOrder> queryTravel(ReqCarStatistics reqCarStatistics) {
        PageHelper.startPage(reqCarStatistics.getPageNum(), reqCarStatistics.getPageSize());
        return (Page<TbTravelOrder>) iTbMapper.queryTravel(reqCarStatistics);
    }

    private void travelOrderPay(TbTravelOrder tbTravelOrder){
        BigDecimal payPrice = tbTravelOrder.getAmount();
        ReqCouponQuery reqCouponQuery = new ReqCouponQuery();
        reqCouponQuery.setStatus(CouponStatus.NOT_USE);
        reqCouponQuery.setOrderBy(" expire_time ");
        reqCouponQuery.setUserId(tbTravelOrder.getUserId());
        List<RespCoupon> respCouponList = couponService.query(reqCouponQuery);
        if (CollectionUtils.isEmpty(respCouponList)){

        } else {
            RespCoupon respCoupon = respCouponList.get(0);
            if (respCoupon.getCouponType() == 1){//折扣券
                payPrice = payPrice.multiply(new BigDecimal(100).subtract((respCoupon.getDiscount().multiply(new BigDecimal(100)))));
            }
            if (respCoupon.getCouponType() == 2){//扣减券
                payPrice = payPrice.subtract(new BigDecimal((respCoupon.getSubAmt()/100)));
            }
            try {
                couponService.useCoupon(tbTravelOrder.getUserId(),respCoupon.getId());
            }catch (Exception e){
                throw new BizException("优惠券抵抗失败:"+e.getMessage());
            }
        }
        //结算
        try{
            userWalletService.changeAmt(tbTravelOrder.getUserId(),-payPrice.longValue()*100,BigDecimal.ZERO,0,payPrice.longValue());
        }catch (Exception e){
            throw new BizException("行程结算失败:"+e.getMessage());
        }
    }

    private TbTravelOrder queryDrivingTravelOrder(Integer carId){
        TbTravelOrderExample tbTravelOrderExample = new TbTravelOrderExample();
        TbTravelOrderExample.Criteria criteria = tbTravelOrderExample.createCriteria();
        criteria.andCarIdEqualTo(carId);
        criteria.andStatusEqualTo((byte)0);
        List<TbTravelOrder> tbTravelOrderList = tbTravelOrderMapper.selectByExample(tbTravelOrderExample);
        if (CollectionUtils.isEmpty(tbTravelOrderList)){
            return null;
        }
        return tbTravelOrderList.get(0);
    }

    private long getTravelOrderTime(Date startTime,Date endTime){
        Calendar dateOne=Calendar.getInstance(),dateTwo=Calendar.getInstance();
        dateOne.setTime(startTime);
        dateTwo.setTime(endTime);
        long timeOne=dateOne.getTimeInMillis();
        long timeTwo=dateTwo.getTimeInMillis();
        long minute=(timeTwo-timeOne)/(1000*60);//转化minut
        return minute;
    }

    public static void main(String args[]){
        String str = null;
        String[] strArray = str.split("-");
        System.out.println(strArray);
    }
}
